/*
* #!
* Ontopoly Editor
* #-
* Copyright (C) 2001 - 2013 The Ontopia Project
* #-
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* !#
*/
package ontopoly.pages;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import net.ontopia.utils.ObjectUtils;
import ontopoly.OntopolyAccessStrategy.Privilege;
import ontopoly.OntopolySession;
import ontopoly.components.AddOrRemoveTypeFunctionBoxPanel;
import ontopoly.components.AssociationTransformFunctionBoxPanel;
import ontopoly.components.CreateInstanceFunctionBoxPanel;
import ontopoly.components.CreateOrCopyInstanceFunctionBoxPanel;
import ontopoly.components.DeleteTopicFunctionBoxPanel;
import ontopoly.components.FieldsEditor;
import ontopoly.components.FunctionBoxPanel;
import ontopoly.components.FunctionBoxesPanel;
import ontopoly.components.InstancePanel;
import ontopoly.components.LinkFunctionBoxPanel;
import ontopoly.components.MenuHelpPanel;
import ontopoly.components.OmnigatorLinkFunctionBoxPanel;
import ontopoly.components.OntopolyBookmarkablePageLink;
import ontopoly.components.TitleHelpPanel;
import ontopoly.components.TopicDropDownChoice;
import ontopoly.components.TopicTypesFunctionBoxPanel;
import ontopoly.components.ViewsFunctionBoxPanel;
import ontopoly.components.VizigatorLinkFunctionBoxPanel;
import ontopoly.model.FieldsView;
import ontopoly.model.Topic;
import ontopoly.model.TopicMap;
import ontopoly.model.TopicType;
import ontopoly.models.AvailableTopicTypesModel;
import ontopoly.models.FieldsViewModel;
import ontopoly.models.HelpLinkResourceModel;
import ontopoly.models.TopicModel;
import ontopoly.models.TopicTypeModel;
import ontopoly.utils.NoSuchTopicException;
import ontopoly.utils.OntopolyUtils;
import org.apache.wicket.Component;
import org.apache.wicket.MarkupContainer;
import org.apache.wicket.Page;
import org.apache.wicket.PageParameters;
import org.apache.wicket.Session;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.model.ResourceModel;
public class InstancePage extends OntopolyAbstractPage {
private TopicModel<Topic> topicModel;
private TopicTypeModel topicTypeModel;
private FieldsViewModel fieldsViewModel;
private boolean isOntologyPage;
public InstancePage() {
}
public InstancePage(PageParameters parameters) {
super(parameters);
String topicMapId = parameters.getString("topicMapId");
String topicId = parameters.getString("topicId");
this.topicModel = new TopicModel<Topic>(topicMapId, topicId);
Topic topic = topicModel.getTopic();
if (topic == null)
throw new NoSuchTopicException("No topic with id " + topicId + " found.");
// if "topicType" parameter is specified, pull out most specific direct type
TopicType tt = null;
String topicTypeId = parameters.getString("topicTypeId");
if (topicTypeId != null)
tt = topic.getMostSpecificTopicType(new TopicTypeModel(topicMapId, topicTypeId).getTopicType());
// if not topic type found, use first available direct type
if (tt == null)
tt = OntopolyUtils.getDefaultTopicType(topic);
this.topicTypeModel = new TopicTypeModel(tt);
String viewId = parameters.getString("viewId");
if (viewId != null)
this.fieldsViewModel = new FieldsViewModel(topicMapId, viewId);
else
this.fieldsViewModel = new FieldsViewModel(FieldsView.getDefaultFieldsView(topic.getTopicMap()));
Privilege privilege = ((OntopolySession)Session.get()).getPrivilege(topic);
// Block access to page if user has privilege NONE
if (privilege == Privilege.NONE) {
setResponsePage(new AccessDeniedPage(parameters));
return;
}
// page is read-only if topic type is read-only
setReadOnlyPage(tt.isReadOnly() ||
ObjectUtils.equals(getRequest().getParameter("ro"), "true") ||
!((AbstractOntopolyPage)this).filterTopic(topic) ||
privilege != Privilege.EDIT);
this.isOntologyPage = (parameters.get("ontology") != null);
// Add form
Form<Object> form = new Form<Object>("form");
add(form);
form.setOutputMarkupId(true);
int subMenuIndex = -1;
if (isOntologyPage) {
// Adding part containing title and help link
add(new MenuHelpPanel("titlePartPanel", AbstractTypesPage.getSubMenuItems(getTopicMapModel()), subMenuIndex,
AbstractTypesPage.getNameModelForHelpLinkAddress(subMenuIndex)));
} else {
// Adding part containing title and help link
TitleHelpPanel titlePartPanel = new TitleHelpPanel("titlePartPanel",
new PropertyModel<String>(topicModel, "name"), new HelpLinkResourceModel("help.link.instancepage"));
titlePartPanel.setOutputMarkupId(true);
add(titlePartPanel);
}
// topic title
form.add(new Label("subTitle", new PropertyModel<String>(topicModel, "name")) {
@Override
public boolean isVisible() {
return isOntologyPage;
}
});
// Add fields panel
createFields(form);
// Function boxes
createFunctionBoxes(form, "functionBoxes");
// initialize parent components
initParentComponents();
}
@Override
protected int getMainMenuIndex() {
return isOntologyPage ? ONTOLOGY_INDEX_IN_MAINMENU : INSTANCES_PAGE_INDEX_IN_MAINMENU;
}
public Topic getTopic() {
return getTopicModel().getTopic();
}
public TopicModel<Topic> getTopicModel() {
return topicModel;
}
public TopicTypeModel getTopicTypeModel() {
return topicTypeModel;
}
public FieldsViewModel getFieldsViewModel() {
return fieldsViewModel;
}
protected boolean isTraversablePage() {
return true; // NOTE: hardcoded
}
private void createFields(Form<Object> form) {
InstancePanel instancePanel = createInstancePanel("instancePanel");
if (instancePanel.isReadOnly()) setReadOnlyPage(true); // page is readonly if instance panel is
form.add(instancePanel);
// if topic is a topic type then display fields editor
Topic topic = getTopicModel().getTopic();
FieldsView fieldsView = getFieldsViewModel().getFieldsView();
if (fieldsView.isDefaultView() && topic.isTopicType() && isOntologyPage)
form.add(new FieldsEditor("fieldsEditor", new TopicTypeModel(new TopicType(topic.getTopicIF(), topic.getTopicMap())), isReadOnlyPage()));
else
form.add(new Label("fieldsEditor").setVisible(false));
}
protected InstancePanel createInstancePanel(final String id) {
return new InstancePanel(id, topicModel, topicTypeModel, fieldsViewModel, isReadOnlyPage(), isTraversablePage()) {
@Override
protected void onLockLost(AjaxRequestTarget target, Topic topic) {
setResponsePage(getPageClass(), getPageParameters());
}
@Override
protected void onLockWon(AjaxRequestTarget target, Topic topic) {
setResponsePage(getPageClass(), getPageParameters());
}
};
}
private void createFunctionBoxes(MarkupContainer parent, String id) {
parent.add(new FunctionBoxesPanel(id) {
@Override
protected List<Component> getFunctionBoxesList(String id) {
List<Component> list = new ArrayList<Component>();
if (getTopicTypeModel().getTopicType() != null) {
list.add(new TopicTypesFunctionBoxPanel(id, getTopicModel(), getTopicTypeModel(), getFieldsViewModel()));
list.add(new ViewsFunctionBoxPanel(id, getTopicModel(), getTopicTypeModel(), getFieldsViewModel()));
Topic topic = getTopicModel().getTopic();
if (topic.isTopicType()) {
list.add(new LinkFunctionBoxPanel(id) {
@Override
protected Component getLabel(String id) {
return new Label(id, new ResourceModel("view.instances.of.this.type"));
}
@Override
protected Component getLink(String id) {
TopicMap tm = getTopicMapModel().getTopicMap();
Topic tt = getTopicModel().getTopic();
Map<String,String> pageParametersMap = new HashMap<String,String>();
pageParametersMap.put("topicMapId", tm.getId());
pageParametersMap.put("topicId", tt.getId());
return new OntopolyBookmarkablePageLink(id, InstancesPage.class, new PageParameters(pageParametersMap), tt.getName());
}
});
}
list.add(new LinkFunctionBoxPanel(id) {
@Override
protected Component getLabel(String id) {
return new Label(id, new ResourceModel("view.instances.of.same.type"));
}
@Override
protected Component getLink(String id) {
TopicMap tm = getTopicMapModel().getTopicMap();
TopicType tt = getTopicTypeModel().getTopicType();
Map<String,String> pageParametersMap = new HashMap<String,String>();
pageParametersMap.put("topicMapId", tm.getId());
pageParametersMap.put("topicId", tt.getId());
return new OntopolyBookmarkablePageLink(id, InstancesPage.class, new PageParameters(pageParametersMap), tt.getName());
}
});
list.add(new LinkFunctionBoxPanel(id) {
@Override
public boolean isVisible() {
return true;
}
@Override
protected Component getLabel(String id) {
return new Label(id, new ResourceModel("edit.type.of.this.instance"));
}
@Override
protected Component getLink(String id) {
TopicMap tm = getTopicMapModel().getTopicMap();
TopicType tt = getTopicTypeModel().getTopicType();
Map<String,String> pageParametersMap = new HashMap<String,String>();
pageParametersMap.put("topicMapId", tm.getId());
pageParametersMap.put("topicId", tt.getId());
pageParametersMap.put("ontology", "true");
//TODO direct link to correct instance page
return new OntopolyBookmarkablePageLink(id, InstancePage.class, new PageParameters(pageParametersMap), tt.getName());
}
});
}
OntopolySession session = (OntopolySession)Session.get();
if(!topicModel.getTopic().isSystemTopic() || session.isAdministrationEnabled()) {
if (getTopicTypeModel().getTopicType() != null) {
// add box for creating new instances of this topic
if (topicModel.getTopic().isTopicType()) {
TopicType topicType = new TopicType(topicModel.getTopic().getTopicIF(), getTopicMapModel().getTopicMap());
if (!topicType.isAbstract() && !topicType.isReadOnly()) {
list.add(new CreateInstanceFunctionBoxPanel(id, getTopicMapModel()) {
@Override
protected Class<? extends Page> getInstancePageClass() {
return InstancePage.class;
}
@Override
protected IModel<String> getTitleModel() {
return new ResourceModel("instances.create.text");
}
@Override
protected Topic createInstance(TopicMap topicMap, String name) {
TopicType topicType = new TopicType(topicModel.getTopic().getTopicIF(), getTopicMapModel().getTopicMap());
return topicType.createInstance(name);
}
@Override
public boolean isVisible() {
return !isReadOnlyPage();
}
});
}
}
// add box for creating a copy of this topic or new instance of the same type
list.add(new CreateOrCopyInstanceFunctionBoxPanel(id, getTopicModel(), getTopicTypeModel()) {
@Override
public boolean isVisible() {
return !isReadOnlyPage();
}
});
list.add(new FunctionBoxPanel(id) {
@Override
public boolean isVisible() {
return !isReadOnlyPage();
}
@Override
protected List<List<Component>> getFunctionBoxComponentList(String id) {
Label label = new Label(id, new ResourceModel("change.type.instance"));
TopicModel<TopicType> selectedModel = new TopicModel<TopicType>(null, TopicModel.TYPE_TOPIC_TYPE);
final boolean isOntologyType = topicModel.getTopic().isOntologyTopic();
AvailableTopicTypesModel choicesModel = new AvailableTopicTypesModel(topicModel) {
@Override
protected boolean filter(Topic o) {
// if current topic is an ontology topic then include ontology types
if (isOntologyType && o.isOntologyType()) return true;
AbstractOntopolyPage page = (AbstractOntopolyPage)getPage();
return page.filterTopic(o);
}
};
TopicDropDownChoice<TopicType> choice = new TopicDropDownChoice<TopicType>(id, selectedModel, choicesModel) {
@Override
protected void onModelChanged() {
super.onModelChanged();
TopicType selectedTopicType = (TopicType)getModelObject();
Topic topic = topicModel.getTopic();
TopicType currentTopicType = getTopicTypeModel().getTopicType();
if (topic.getTopicTypes().contains(currentTopicType)) {
// Only replace current topic type if it still is an existing type of the current topic.
// This can actually happen if the user uses the back button in the browser.
topic.addTopicType(selectedTopicType);
topic.removeTopicType(currentTopicType);
}
Map<String,String> pageParametersMap = new HashMap<String,String>();
pageParametersMap.put("topicMapId", topic.getTopicMap().getId());
pageParametersMap.put("topicId", topic.getId());
pageParametersMap.put("topicTypeId", selectedTopicType.getId());
setResponsePage(InstancePage.class, new PageParameters(pageParametersMap));
}
};
choice.add(new AjaxFormComponentUpdatingBehavior("onchange") {
@Override
protected void onUpdate(AjaxRequestTarget target) {
}
});
List<Component> heading = Arrays.asList(new Component[] { label });
List<Component> box = Arrays.asList(new Component[] { choice });
List<List<Component>> result = new ArrayList<List<Component>>(2);
result.add(heading);
result.add(box);
return result;
}
});
if(session.isAdministrationEnabled()) {
list.add(new AddOrRemoveTypeFunctionBoxPanel(id, topicModel) {
@Override
public boolean isVisible() {
return !isReadOnlyPage();
}
});
}
if (getTopicModel().getTopic().isAssociationType()) {
list.add(new AssociationTransformFunctionBoxPanel(id, topicModel) {
@Override
public boolean isVisible() {
return !isReadOnlyPage();
}
});
}
if (!topicModel.getTopic().isTopicMap()) {
list.add(new DeleteTopicFunctionBoxPanel(id) {
@Override
public boolean isVisible() {
return !isReadOnlyPage();
}
@Override
public TopicModel<Topic> getTopicModel() {
return InstancePage.this.getTopicModel();
}
@Override
public void onDeleteConfirmed(Topic _topic) {
Topic topic = (Topic)_topic;
TopicMap topicMap = topic.getTopicMap();
TopicType topicType = getTopicTypeModel().getTopicType();
Map<String,String> pageParametersMap = new HashMap<String,String>();
pageParametersMap.put("topicMapId", topicMap.getId());
pageParametersMap.put("topicId", topicType.getId());
setResponsePage(InstancesPage.class, new PageParameters(pageParametersMap));
}
});
}
}
}
list.add(new OmnigatorLinkFunctionBoxPanel(id) {
@Override
protected String getTopicMapId() {
return getTopicMapModel().getTopicMap().getId();
}
@Override
protected String getTopicId() {
Topic tt = getTopicModel().getTopic();
return tt.getId();
}
});
list.add(new VizigatorLinkFunctionBoxPanel(id) {
@Override
protected String getTopicMapId() {
return getTopicMapModel().getTopicMap().getId();
}
@Override
protected String getTopicId() {
Topic tt = getTopicModel().getTopic();
return tt.getId();
}
});
return list;
}
});
}
@Override
public void onDetach() {
topicModel.detach();
topicTypeModel.detach();
fieldsViewModel.detach();
super.onDetach();
}
}